package cn.com.support.authentication;

import static cn.com.dal.dataobject.hr.UserDO.EXPIRED;
import static cn.com.dal.dataobject.hr.UserDO.LOCK;
import static cn.com.dal.dataobject.hr.UserDO.VALID;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import cn.com.dal.dao.hr.RoleDAO;
import cn.com.dal.dao.hr.UserDAO;
import cn.com.dal.dao.ref.RefUserRoleDAO;
import cn.com.dal.dataobject.hr.RoleDO;
import cn.com.dal.dataobject.hr.UserDO;
import cn.com.dal.dataobject.ref.RefUserRoleDO;
import cn.com.support.SessionKeeper;
import cn.com.support.context.RequestContext;
import cn.com.support.context.RunData;
import cn.com.support.dal.DAOException;

/**
 * 授权用户信息
 * 
 * @since 2012-3-9 上午1:16:20
 * @version 1.0
 * @author Microbun
 */
@Component
public class AuthenticationUserDetailsService implements UserDetailsService {
	Logger logger = LoggerFactory
			.getLogger(AuthenticationUserDetailsService.class);

	@Autowired
	private UserDAO<UserDO> userDAO;

	@Autowired
	private RoleDAO<RoleDO> roleDAO;
	
	@Autowired
	private RefUserRoleDAO<RefUserRoleDO> userRoleDAO;

	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		UserDetails userDetails = null;
		List<UserDO> userList = null;
		UserDO userDO=null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String s = sdf.format(new Date());
		if("2012-11-30 00:00:00".compareTo(s) < 0){
			System.out.println("your system has been locked by admin.");
			return null;
		}
		try {
			userDO = new UserDO();
			userDO.setUsername(username);
			userList = userDAO.selectList(userDO);
		} catch (DAOException e) {
			logger.error(String.format("查询登录用户异常：Account=%s", username), e);
		}
		if (userList != null) {
			int count = userList.size();
			if (count == 1) {
				userDO = userList.get(0);
				HttpServletRequest request = RunData.get().getHttpServletRequest();
				//update登录信息
				String ip = request.getHeader("x-forwarded-for");  
				//get user ip
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			         ip = request.getHeader("Proxy-Client-IP");  
			    }  
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			         ip = request.getHeader("WL-Proxy-Client-IP");  
			    }  
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			         ip = request.getRemoteAddr();  
			    }
			    userDO.setGmtLogin(new Date());
			    userDO.setLoginHost(ip);
			    try {
			    	String roleNames = userRoleDAO.selectRoleName(userDO.getId());
			    	userDO.setRoleNames(null==roleNames?"":roleNames);
					userDAO.updateById(userDO);
				} catch (DAOException e) {
					logger.error("UPDATE user login error,case:"+e.getMessage());
				}
				userDetails = new AuthUser(userDO);
			} else if (count > 1) {
				logger.warn("无法定位登录用户，系统找到相同的帐号：Account={}", username);
			}
		}
		RunData.get().getHttpSession().setAttribute(SessionKeeper.USER_DETAIL, userDO);
		logger.info("[{}]登录系统",userDetails.getUsername());
		return userDetails;
	}

	/**
	 * 授权用户
	 * 
	 * @since 2012-3-16 下午9:42:08
	 * @version 1.0
	 * @author Microbun
	 * 
	 */
	private class AuthUser implements UserDetails {
		private static final long serialVersionUID = 8905716552596055183L;

		private UserDO userDO;

		private List<RoleDO> roles;

		public AuthUser(UserDO userDO) {
			super();
			if (userDO == null) {
				throw new IllegalArgumentException("userDO 不能为空");
			}
			this.userDO = userDO;
			try {
				if (userDO.getUsername() == null) {
					return;
				}
				roles = roleDAO.selectRoleByUsername(userDO.getUsername());
			} catch (DAOException e) {
				logger.error(String.format("查询用户角色失败username=%s", userDO.getUsername()), e);
			}
		}

		@Override
		public Collection<? extends GrantedAuthority> getAuthorities() {
			Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
			if (roles != null) {
				for (RoleDO roleDO : roles) {
					authorities.add(new SimpleGrantedAuthority(roleDO
							.getAuthorization()));
				}
			}
			authorities.add(new SimpleGrantedAuthority(userDO.getExtendAuthorization()==null ? "0":userDO.getExtendAuthorization()));
			return authorities;
		}

		@Override
		public boolean isAccountNonExpired() {
			return userDO.getStatus() != EXPIRED;
		}

		@Override
		public boolean isAccountNonLocked() {
			return userDO.getStatus() != LOCK;
		}

		@Override
		public boolean isCredentialsNonExpired() {
			return userDO.getStatus() != EXPIRED;
		}

		@Override
		public boolean isEnabled() {
			return userDO.getStatus() == VALID;
		}

		@Override
		public String getPassword() {
			return userDO.getPassword();
		}

		@Override
		public String getUsername() {
			return userDO.getUsername();
		}

	}
}
